/**
 * KopsoxFramework
 * Copyright (C) 2010 Free Software Foundation, Inc. <http://fsf.org/>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.kopsox.validation.impl;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.kopsox.comm.message.ErrorMessage;
import org.kopsox.general.priority.Priority;
import org.kopsox.general.priority.PriorityEnum;
import org.kopsox.validation.Validator;
import org.kopsox.validation.handler.ValidationErrorHandler;

/**
 * @author Konrad Renner - 08.09.2010
 *
 */
public abstract class AbstractValidator implements Validator {

	private static final long serialVersionUID = 8574004235953607610L;
	private final Set<ValidationErrorHandler> handlers;
	protected final List<ErrorMessage> errorMessages;
	private Priority priority;
	
	public AbstractValidator(){
		this.handlers = new HashSet<ValidationErrorHandler>();
		this.errorMessages = new ArrayList<ErrorMessage>();
		this.priority = PriorityEnum.MEDIUM.getPriority();
	}
	
	/* (non-Javadoc)
	 * @see org.kopsox.validation.Validator#addHandler(org.kopsox.validation.handler.ValidationErrorHandler)
	 */
	@Override
	public void addHandler(ValidationErrorHandler handler) {
		handlers.add(handler);
	}

	/* (non-Javadoc)
	 * @see org.kopsox.validation.Validator#delegateErrorsToHandlers()
	 */
	@Override
	public void delegateErrorsToHandlers() {
		for(ValidationErrorHandler handler:this.handlers){
			handler.handleValidationError(this.errorMessages);
		}
	}

	/* (non-Javadoc)
	 * @see org.kopsox.validation.Validator#getValidationErrors()
	 */
	@Override
	public List<ErrorMessage> getValidationErrors() {
		return this.errorMessages;
	}

	/* (non-Javadoc)
	 * @see org.kopsox.validation.Validator#removeHandler(org.kopsox.validation.handler.ValidationErrorHandler)
	 */
	@Override
	public void removeHandler(ValidationErrorHandler handler) {
		this.handlers.remove(handler);
	}

	/* (non-Javadoc)
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	@Override
	public int compareTo(Validator o) {
		
		//it is not allowed that the same validator is added twice
		if(getClass().equals(o.getClass())) {
			return 0;
		}
		
		if(this.priority.compareTo(o.getPriority()) == 0) {
			//show-stopping validators are the most important ones
			if(isShowStoppingValidator() || o.isShowStoppingValidator()) {
				
				if(isShowStoppingValidator() && o.isShowStoppingValidator()) {
					return getClass().getName().compareTo(o.getClass().getName());
				}else if(isShowStoppingValidator() && !o.isShowStoppingValidator()) {
					return -1;
				}else {
					return 1;
				}
			}
			
			return getClass().getName().compareTo(o.getClass().getName());
		}
		return this.priority.compareTo(o.getPriority());
	}

	@Override
	public Priority getPriority() {
		return this.priority;
	}

	@Override
	public void setPriority(Priority priority) {
		this.priority = priority;
	}

	/* (non-Javadoc)
	 * @see org.kopsox.validation.Validator#isShowStoppingValidator()
	 */
	@Override
	public boolean isShowStoppingValidator() {
		return false;
	}
	
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append(getClass().getName());
		sb.append('[');
		sb.append("priority=");
		sb.append(priority);
		sb.append(",handlers=");
		sb.append(handlers);
		sb.append(",errorMessages=");
		sb.append(errorMessages);
		sb.append(']');
		
		return sb.toString();
	}
	
	@Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                        + ((errorMessages == null) ? 0 : errorMessages.hashCode());
        result = prime * result
                        + ((handlers == null) ? 0 : handlers.hashCode());
        result = prime * result
                        + ((priority == null) ? 0 : priority.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
                return true;
        if (obj == null)
                return false;
        if (getClass() != obj.getClass())
                return false;
        AbstractValidator other = (AbstractValidator) obj;
        if (errorMessages == null) {
                if (other.errorMessages != null)
                        return false;
        } else if (!errorMessages.equals(other.errorMessages))
                return false;
        if (handlers == null) {
                if (other.handlers != null)
                        return false;
        } else if (!handlers.equals(other.handlers))
                return false;
        if (priority == null) {
                if (other.priority != null)
                        return false;
        } else if (!priority.equals(other.priority))
                return false;
        return true;
    }
}
